<?php
/**
-------------------------
GNU GPL COPYRIGHT NOTICES
-------------------------
This file is part of FlexicaCMS.

FlexicaCMS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FlexicaCMS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FlexicaCMS.  If not, see <http://www.gnu.org/licenses/>.*/

/**
 * $Id$
 *
 * @author FlexicaCMS team <contact@flexicacms.com>
 * @link http://www.flexicacms.com/
 * @copyright Copyright &copy; 2009-2010 Gia Han Online Solutions Ltd.
 * @license http://www.flexicacms.com/license.html
 */
class CmsEmail
{
    public $params;

    /**
     * Email subject
     *
     * @var string
     */
    public $subject;

    /**
     * From address
     *
     * @var string
     */
    public $from;

    /**
     * address string or array (address=> name)
     *
     * @var mixed
     */
    public $to;

    /**
     * address string or array (address=> name)
     *
     * @var mixed
     */
    public $cc;

    /**
     * address string or array (address=> name)
     *
     * @var mixed
     */
    public $bcc;

    /**
     * Email body
     *
     * @var string
     */
    public $body;

    /**
     * Email attachments
     *
     * @var array
     */
    public $attachments;

    /**
     * Batch send flag
     *
     * @var bool
     */
    public $isBatchSend = false;

    /**
     * Send mail method which is smtp, sendmail or mail
     *
     * @var mixed
     */
    public $sendMailMethod = 'smtp';

    /**
     * Email content type
     *
     * @var mixed
     */
    public $contentType = 'text/html';

    public $viewPath;

    private $_data;

    public $subjectParams = array();

    public function __construct()
    {

        $template = $this->template;
        //template is the page alias
        $page = Page::model()->with('defaultUrl')->findByAttributes(array('alias' => $template));
        $reuqestedPageUrl = $page->defaultUrl->url;

        //email subject is now managed by locale taxonomy with vocabulary type is email-subjects
        if (empty($this->locale)) // Get default locale ID
            $this->locale = str_replace('_', '/', strtolower(Yii::app()->locale->id));
        $criteria = new CDbCriteria();
        $criteria->join = "INNER JOIN " . SITE_TABLE_PREFIX . "taxonomy_vocabulary tv ON  tv.id=t.v_id INNER JOIN " . SITE_TABLE_PREFIX . "taxonomy_term_hierarchy tth ON  tth.term_id=t.id ";
        $criteria->compare('tv.alias', 'email-subjects');
        //term alias is page alias, which has value is $template
        $criteria->compare('t.alias', $template);
        $criteria->addCondition('tth.parent_id IN (SELECT id FROM ' . SITE_TABLE_PREFIX . 'taxonomy_term t1 WHERE t1.name=:locale ) ');
        $criteria->params = CMap::mergeArray($criteria->params, array(':locale' => $this->locale));
        $term = Term::model()->find($criteria);
        if ($term) {
            $this->subject = $term->description;
        }
        else $this->subject = $page->title;
        // bind params into subject
        if (is_array($this->subjectParams) && count($this->subjectParams) > 0)
        {
            $paramNames = array();
            $paramValues = array();
            foreach($this->subjectParams as $key => $value)
            {
                $paramNames[] = '{'.$key.'}';
                $paramValues[] = $value;    
            }
            $this->subject = str_replace($paramNames,$paramValues,$this->subject);
        }
        //select name from term where v_id=13 and alias=$template and id in (select id from )

        // $this->subject=$page->title;


        Yii::import('Cms.controllers.DefaultCmsController');
        $oldController = Yii::app()->controller;
        Yii::app()->controller = new DefaultCmsController('DefaultCmsController');
        Yii::app()->theme = Settings::THEME;

        $_GET['preview'] = 1;
        $host = str_replace('http://', '', Yii::app()->request->hostInfo);
        $html = FSM::run('Cms.Page.renderPage', array('url' => $reuqestedPageUrl, 'host' => $host))->html;
        Yii::app()->controller = $oldController;

        //process for html template

        $result = FSM::run('Cms.workflow.lookup');
        $filepath = Yii::app()->runtimePath . '/emails/' . $result->model->name;
        if (!is_dir($filepath)) {
            $r = mkdir($filepath, 0777, true);
            if (!$r) {
                throw new CHttpException(501, 'Can not create folder');
            }
        }
        $filepath = $filepath . '' . str_replace('.html', '.php', $reuqestedPageUrl);
        //cleanup
        $dom = new DOMDocument;
        $dom->loadHTML($html);
        $body = $dom->getElementsByTagName('body')->item(0);

        $newDom = new DOMDocument;
        $newDom->loadXML('<p></p>');
        $root = $newDom->getElementsByTagName('p')->item(0);
        if ($body->childNodes->length) {
            foreach ($body->childNodes as $child)
            {
                /** @var DOMNode */
                if ($child->nodeName !== 'script') {
                    $child = $newDom->importNode($child, true);
                    $newDom->documentElement->appendChild($child);
                }
            }
        }
        $html = $newDom->saveXML($root);

        if (preg_match_all('/#([a-zA-Z0-9_]*?)#/', $html, $match)) {
            foreach ($match[0] as $key => $matchItem) {
                if (strpos($matchItem, 'Settings::')) {
                    $html = str_replace($matchItem, "<?php echo " . $match[1][$key] . ";?>", $html);
                }
                else {
                    $html = str_replace($matchItem, "<?php echo $" . $match[1][$key] . ";?>", $html);
                }
            }
        }

        if (is_file($filepath)) {
            file_put_contents($filepath, $html);
        } else {
            $f = fopen($filepath, 'w+');
            if ($f == false) {
                throw new CHttpException(400, Yii::t('Core', 'Cannot open file template.'));
            }
            fwrite($f, $html);
            fclose($f);
        }
        $this->viewPath = $filepath;

    }

    public function getData()
    {
        $data = array();
        foreach ($this->getParameters() as $key => $value) {
            $method = "get{$key}";
            $data[$key] = $this->$method();
        }
        return $data;
    }

    public function send()
    {
        $this->_data = $this->getData();
        if (isset(Yii::app()->controller))
            $controller = Yii::app()->controller;
        else
            $controller = new CController('YiiMail');

        // renderPartial won't work with CConsoleApplication, so use
        // renderInternal - this requires that we use an actual path to the
        // view rather than the usual alias
        $viewPath = $this->viewPath;
        $this->body = $controller->renderInternal($viewPath, $this->_data, true);

        //fix can not autoloader in swiftMailer
        Yii::import('Core.extensions.vendors.mail.vendors.swiftMailer.classes.Swift', true);
        Yii::registerAutoloader(array('Swift', 'autoload'));
        Yii::import('Core.extensions.vendors.mail.vendors.swiftMailer.swift_init', true);
        //end fix
        //            require_once(dirname(__FILE__).'/../../Core/extensions/vendors/mail/vendors/SwiftMailer/swift_required.php');

        switch ($this->sendMailMethod) {
            case 'smtp':
                $transport = Swift_SmtpTransport::newInstance();
                $transport->setHost(Settings::SMTP_HOST);
                $transport->setPort(Settings::SMTP_PORT);
                if (trim(Settings::SMTP_SECURE) != '')
                    $transport->setEncryption(Settings::SMTP_SECURE);
                if (trim(Settings::SMTP_USERNAME) != '')
                    $transport->setUsername(Settings::SMTP_USERNAME);
                if (trim(Settings::SMTP_PASSWORD) != '')
                    $transport->setPassword(Settings::SMTP_PASSWORD);
                break;
            case 'sendmail':
                $transport = Swift_SendmailTransport::newInstance('/usr/sbin/exim -bs');
                break;
            case 'mail':
                $transport = Swift_SendmailTransport::newInstance();
            default:
                break;
        }

        $mailer = Swift_Mailer::newInstance($transport);
        $message = Swift_Message::newInstance();
        if (!empty($this->contentType)) {
            $message->setContentType($this->contentType);
        }
        $message->setFrom(array(Settings::MAIL_SERDER_ADDRESS => Settings::MAIL_SENDER_NAME));
        $message->setSubject($this->subject);

        $message->setBody($this->body);

        if (is_array($this->attachments))
            foreach ($this->attachments as $file)
                $message->attach(Swift_Attachment::fromPath($file));
        //Send email
        $this->addMailAddresses($message, $this->to);
        $this->addMailAddresses($message, $this->cc, 'cc');
        $this->addMailAddresses($message, $this->bcc, 'bcc');

        if ($this->isBatchSend)
            $result = $mailer->batchSend($message);
        else
            $result = $mailer->send($message);

        return $result;
    }

    /**
     *
     * @param $mail
     * @param $addresses array or string
     * @param string $field
     * @return mixed
     */
    public function addMailAddresses(&$mail, $addresses, $field = 'to')
    {
        if (empty($addresses))
            return;
        if (!is_array($addresses))
            $addresses = array($addresses=>'');
        foreach ($addresses as $address => $name) {
            switch ($field) {
                case 'cc':
                    $mail->addCc($address, $name);
                    break;
                case 'bcc':
                    $mail->addBcc($address, $name);
                    break;
                default:
                    $mail->addTo($address, $name);
                    break;
            }
        }
    }

}

?>